/*
etc 包是项目的启动配置核心模块，专注于集群配置、服务组件配置等基础启动配置的管理。
核心特性：
1. 配置仅支持通过配置文件进行初始化，不支持通过 master 管理服动态修改
2. 内部维护全局配置管理器，统一封装配置的查询、设置、匹配等操作
3. 配置路径支持通过环境变量、命令行参数指定，默认使用 ./etc 目录
*/
package etc

import (
	"context"
	"fmt"
	"os"
	"path/filepath"

	"gameServer/config"
	"gameServer/config/filesource"
	"gameServer/core/value"
	"gameServer/log"
)

// 常量定义：配置路径的相关标识（环境变量名、命令行参数名、默认路径）
const (
	dueEtcEnvName  = "R_DUE_ETC" // 指定配置路径的环境变量名，外部可通过该环境变量自定义配置目录
	dueEtcArgName  = "etc"       // 指定配置路径的命令行参数名，外部可通过命令行参数覆盖配置目录
	defaultEtcPath = "./etc"     // 配置文件的默认路径，当环境变量和命令行参数都未指定时使用
)

// globalConfigManager 全局配置管理器实例
// 负责加载配置文件、管理配置源，提供配置的查询、设置、匹配等核心能力
var (
	globalConfigManager config.ConfigManager
	globalConfig        []*config.Config // 修改为正确的配置数据类型
)

// init 包初始化函数，程序启动时自动执行
// 作用：初始化全局配置管理器，确定配置文件路径并加载文件配置源
func init() {
	if err := Init(); err != nil {
		panic(fmt.Sprintf("初始化配置失败: %v", err))
	}
}

// 获取配置路径
func getConfigPath() string {
	path := os.Getenv("R_DUE_ETC")
	if path != "" {
		absPath, err := filepath.Abs(path)
		if err != nil {
			log.Fatalf("获取绝对路径失败: %v", err)
		}
		// 验证目录是否存在
		if _, err := os.Stat(absPath); err != nil {
			log.Fatalf("配置目录不存在: %v", err)
		}
		return absPath
	}
	// 使用正确的默认配置目录路径
	defaultPath := filepath.Join("etc", "etc", "etc_demo")
	absPath, err := filepath.Abs(defaultPath)
	if err != nil {
		log.Fatalf("获取默认路径绝对路径失败: %v", err)
	}
	// 验证默认目录是否存在
	if _, err := os.Stat(absPath); err != nil {
		log.Fatalf("默认配置目录不存在: %v", err)
	}
	return absPath
}

// GetGlobalConfig 返回全局配置数据
func GetGlobalConfig() []*config.Config {
	return globalConfig
}

// Init 初始化配置管理器
func Init() error {
	configPath := getConfigPath()

	// 创建文件配置源 - 使用正确的参数顺序和模式
	fileSource := filesource.NewFileSource(configPath, config.ConfigMode("local"))

	// 从配置路径推导项目根目录 (配置路径格式: .../game_server/etc/etc/etc_demo)
	rootDir := filepath.Dir(filepath.Dir(filepath.Dir(configPath)))

	// 构建日志文件路径
	logPath := filepath.Join(rootDir, "config_debug.log")

	// 确保日志目录存在
	logDir := filepath.Dir(logPath)
	if err := os.MkdirAll(logDir, 0755); err != nil {
		return fmt.Errorf("创建日志目录失败: %v", err)
	}

	f, err := os.Create(logPath)
	if err != nil {
		return fmt.Errorf("创建日志文件失败: %v", err)
	}
	defer f.Close()

	// 记录配置路径
	if _, err := f.WriteString("配置文件路径: " + configPath + "\n"); err != nil {
		return fmt.Errorf("写入配置路径日志失败: %v", err)
	}

	// 加载配置
	configs, err := fileSource.Load(context.Background(), "config.json")
	if err != nil {
		if _, writeErr := f.WriteString("加载配置失败: " + err.Error() + "\n"); writeErr != nil {
			return fmt.Errorf("加载配置失败并写入错误日志失败: %v, 日志错误: %v", err, writeErr)
		}
		return err
	}

	// 记录配置数量
	configCount := len(configs)
	if _, err := f.WriteString(fmt.Sprintf("成功加载配置数量: %d\n", configCount)); err != nil {
		return fmt.Errorf("写入配置数量日志失败: %v", err)
	}

	// 存储配置到全局变量
	globalConfig = configs

	// 创建配置管理器
	globalConfigManager = config.NewManager(config.SetSources(fileSource))

	return nil
}

// SetConfigManager 手动设置全局配置管理器（支持外部自定义配置管理器替换默认实现）
// 参数：
//
//	manager - 自定义的配置管理器实例（需实现 config.ConfigManager 接口）
func SetConfigManager(manager config.ConfigManager) {
	// 若当前已有全局配置管理器实例，先关闭原有实例释放资源（避免资源泄露）
	if globalConfigManager != nil {
		globalConfigManager.Close()
	}
	// 用传入的自定义管理器替换全局实例
	globalConfigManager = manager
}

// GetConfigManager 获取全局配置管理器实例
// 返回值：
//
//	config.ConfigManager - 全局配置管理器，供外部直接操作配置源或扩展配置能力
func GetConfigManager() config.ConfigManager {
	return globalConfigManager
}

// Has 判断指定模式的配置是否存在
// 参数：
//
//	pattern - 配置的匹配模式（字符串类型），支持精确键名或模糊匹配规则（规则由 config.ConfigManager 实现定义）
//
// 返回值：
//
//	bool - 配置存在性标识（true 表示存在，false 表示不存在）
func Has(pattern string) bool {
	// 委托全局配置管理器的 Has 方法实现配置存在性判断
	return globalConfigManager.Has(pattern)
}

// Get 获取指定模式的配置值
// 参数：
//
//	pattern - 配置的匹配模式（字符串类型），用于定位目标配置
//
// 返回值：
//
//	value.Value - 包装后的配置值，若配置不存在则返回 value.Value 空实例
func Get(pattern string) value.Value {
	// 委托全局配置管理器的 Get 方法实现配置值查询，统一返回 value.Value 类型
	return globalConfigManager.Get(pattern)
}

// Set 设置指定模式的配置值（注意：etc 包配置源默认为只读，该方法可能执行失败）
// 参数：
//
//	pattern - 配置的匹配模式（字符串类型），用于指定要设置的配置项
//	value - 要设置的配置值（value.Value 类型），需与配置项的预期类型匹配
//
// 返回值：
//
//	error - 操作错误（如配置源为只读、模式格式非法等场景会返回非 nil 错误）
func Set(pattern string, value value.Value) error {
	// 委托全局配置管理器的 Set 方法实现配置值设置
	return globalConfigManager.Set(pattern, value)
}

// Match 匹配多个符合模式的配置项
// 参数：
//
//	pattern - 可变参数（字符串类型），支持传入多个配置匹配模式
//
// 返回值：
//
//	config.Matcher - 配置匹配器实例，可通过该实例遍历所有匹配的配置项
func Match(pattern ...string) config.Matcher {
	// 委托全局配置管理器的 Match 方法实现多模式配置匹配，返回匹配器供外部遍历
	return globalConfigManager.Match(pattern...)
}

// Close 关闭全局配置管理器，释放配置源相关资源（如文件句柄、连接等）
func Close() {
	// 委托全局配置管理器的 Close 方法实现资源释放
	globalConfigManager.Close()
}
